/*
 moxl - Modular XML Library
 Copyright (c) 2007, Malcolm Sparks

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package moxl.dom;

import java.util.HashMap;
import java.util.Map;

public class XmlNamespaceContext
{
	private final XmlNamespaceContext parent;

	private XmlNamespace currentNonprefixedNamespace;

	private Map<String, XmlNamespace> prefixRegistry;

	public XmlNamespaceContext()
	{
		this((XmlNamespaceContext) null);
	}

	private XmlNamespaceContext(XmlNamespaceContext parent)
	{
		this.parent = parent;
	}

	public XmlNamespaceContext(XmlNamespace namespace)
	{
		this((XmlNamespaceContext) null);
		currentNonprefixedNamespace = namespace;
	}

	public void registerNamespace(String prefix, XmlNamespace namespace)
	{
		ensurePrefixRegistry();
		prefixRegistry.put(prefix, namespace);
	}

	private void ensurePrefixRegistry()
	{
		if (prefixRegistry == null)
		{
			prefixRegistry = new HashMap<String, XmlNamespace>();
		}
	}

	private XmlNamespace getCurrentNonprefixedNamespace()
	{
		if (currentNonprefixedNamespace != null)
		{
			return currentNonprefixedNamespace;
		}
		if (parent != null)
		{
			return parent.getCurrentNonprefixedNamespace();
		}
		return DefaultXmlNamespace.getInstance();
	}

	public QualifiedName qualifyElementName(String tag)
	{
		int colon = tag.indexOf(':');
		if (colon == -1)
		{
			return new DefaultQualifiedName(getCurrentNonprefixedNamespace(), tag);
		}
		String prefix = tag.substring(0, colon);
		XmlNamespace namespace = getNamespaceForPrefix(prefix);
		if (namespace == null)
		{
			if (parent != null)
			{
				return parent.qualifyElementName(tag);
			}
			return new DefaultQualifiedName(DefaultXmlNamespace.getInstance(), tag);
		}
		String localPart = tag.substring(colon + 1);
		return new DefaultQualifiedName(namespace, localPart);
	}

	private XmlNamespace getNamespaceForPrefix(String prefix)
	{
		if (prefixRegistry == null)
		{
			return null;
		}
		return prefixRegistry.get(prefix);
	}

	public QualifiedName qualifyAttributeName(String tag)
	{
		int colon = tag.indexOf(':');
		if (colon == -1)
		{
			return new DefaultQualifiedName(DefaultXmlNamespace.getInstance(), tag);
		}
		String prefix = tag.substring(0, colon);
		XmlNamespace namespace = getNamespaceForPrefix(prefix);
		if (namespace == null)
		{
			if (parent != null)
			{
				return parent.qualifyAttributeName(tag);
			}
			return new DefaultQualifiedName(DefaultXmlNamespace.getInstance(), tag);
		}
		String localPart = tag.substring(colon + 1);
		return new DefaultQualifiedName(namespace, localPart);
	}

	public XmlNamespaceContext spawnContext()
	{
		return new XmlNamespaceContext(this);
	}

	public void setNonprefixedNamespace(XmlNamespace namespace)
	{
		this.currentNonprefixedNamespace = namespace;
	}

	public XmlNamespace lookupNamespace(String prefix)
	{
		if (prefix == null)
		{
			throw new IllegalArgumentException("Prefix cannot be null");
		}
		if (prefix.equals(""))
		{
			throw new IllegalArgumentException("Prefix cannot be blank");
		}
		if (prefixRegistry == null)
		{
			DefaultXmlNamespace.getInstance();
		}
		return prefixRegistry.get(prefix);
	}
}
